<?php

class contenite_controller extends app_controller {
  public $EXCLUDED = array('contrib', 'myadmin');
  
  /**
   * Action
   */
  function pack($archive = 'tmp/contenite.lib', $dir = 'src') {
    $this->rendered = TRUE;
    //$this->layout = FALSE;
    
    $output = 'Packing ...<br/>';

    chdir($_SERVER['DOCUMENT_ROOT']); 

    $files = array();

    $f = fopen($archive, 'wb');
    if (!$f) {
      $output .= "Can't write to $archive: " . posix_strerror(posix_get_last_error());
      return;
    }

    $output .= $this->_pack($dir, $dir, $files);

    fwrite($f, sprintf('CONTENITE:%-3d:', FORMAT_VERSION));

    $pos = 26;
    fseek($f, $pos);
    $cat = array();
    foreach ($files as $file) {
      $entry = preg_replace('#^[^/]+#', '', $file);
      if (is_dir($file)) {
        $cat[$entry] = 'd';
        $output .= "Packing $file (directory) ...<br/>\n";
        continue;
      }
      $data = file_get_contents($file);
      $orig_len = strlen($data);
      $data = gzencode($data);
      if (!$data) {
        $output .= "Can't pack $file - skipped<br/>\n";
        continue;
      }
      $len = strlen($data);
      $cat[$entry] = array($pos, $len, $orig_len);
      $output .= "Packing $file (pos=$pos, len=$len) ...<br/>\n";
      fwrite($f, $data);
      $pos += $len;
    }
    //D echo "Cat @", $pos, ", tell=", ftell($f);

    fwrite($f, serialize($cat));
    fseek($f, 14);
    fprintf($f, '%-11d:', $pos);
    fclose($f);
    
    return $output . '... done';
  }

  /**
   * Helper
   */
  function _pack($dir, $root, &$files) {
    $output = '';
    
    $d = opendir($dir);
    if (!$d) die("Can't open $dir");
    while ($entry = readdir($d)) {
      if (preg_match('/^\./', $entry)) continue;
      if (preg_match('/\~$/', $entry)) continue;
      if (in_array($entry, $this->EXCLUDED)) {
        $output .= $entry . " excluded<br/>\n";
        continue;
      }
      $path = $dir . '/' . $entry;
      $files[] = $path;
      if (is_dir($path)) {
        $this->_pack($path, $dir, $files);
      }
    }
    closedir($d);
    return $output;
  }
}
